let target: RuntimeFunction = null; // 标记运行时函数

// 观察者定义
function Watcher(func: Function) {
    target = func;
    target();
    target = null;
}

// 依赖类定义
class Dep {
    subscribers: Function[];// 依赖函数（订阅者）列表
    constructor() {
        this.subscribers = []// 初始化订阅者列表
    }
    // 添加数据的依赖
    depend() {
        // 保证订阅者的唯一性且只记录函数运行时的依赖
        if (target instanceof Function && !this.subscribers.includes(target)) {
            this.subscribers.push(target);
        }
    }
    // 更新所有依赖
    notify() {
        this.subscribers.forEach(sub => sub());
    }
}

// 映射哈希表
const depsMap = new Map<string, Dep>();

// 获得响应式对象
function reactive<T extends Object>(target: T) {
    // 为对象的每个属性都创建依赖类存储
    Object.keys(target).forEach((key: string) => {
        depsMap.set(key, new Dep());
    });
    // 设置代理对象trap
    return new Proxy(target, {
        get(target: T, prop: string, receiver) {
            (depsMap.get(prop) as Dep).depend();// 收集依赖
            return Reflect.get(target, prop, receiver);
        },
        set(target: T, prop: string, value: any, receiver) {
            let res = Reflect.set(target, prop, value, receiver);
            (depsMap.get(prop) as Dep).notify();// 更新依赖
            return res;
        }
    });
}

// 测试用例
let product1:any = {
    price: 10,
    discount: 0.9,
    quantity: 5
};
let proxy_product1 = reactive(product1);
let realPrice = 0;
let total2 = 0;
Watcher(() => total2 = proxy_product1.price * proxy_product1.quantity);
Watcher(() => realPrice = proxy_product1.discount * proxy_product1.price);
console.log(realPrice);// 9
console.log(total2);// 50
proxy_product1.quantity = 15;
console.log(total2);// 150
proxy_product1.price = 20;
console.log(realPrice); // 18

// 当在映射表中设置了新属性之后，proxy对象新添加的属性仍然是响应式的
depsMap.set("minus",new Dep());
let realPrice2 = 0;
proxy_product1.minus = 3;
Watcher(()=>realPrice2 = proxy_product1.price - proxy_product1.minus);
console.log(realPrice2);// 17
proxy_product1.minus = 5;
console.log(realPrice2);// 15

